using System;

namespace CombatTracker.Creatures
{
  public class Creature : IComparable<Creature>, IEquatable<Creature>
  {
    #region Private Fields

    private string _name;
    private int _initiativeBonus;
    private int _initiativeRoll;
    private CreatureType _type;
    private InitiativeState _initiativeState;

    #endregion

    #region Constructors

    public Creature()
    {
      _name = String.Empty;
      _initiativeBonus = 0;
      _initiativeRoll = 0;
      _type = CreatureType.Monster;
      _initiativeState = InitiativeState.OutOfCombat;
    }

    #endregion

    #region Properties

    public string Name
    {
      get { return _name; }
      set { _name = value; }
    }

    public int InitiativeBonus
    {
      get { return _initiativeBonus; }
      set { _initiativeBonus = value; }
    }

    public int InitiativeRoll
    {
      get { return _initiativeRoll; }
      set { _initiativeRoll = value; }
    }

    public CreatureType Type
    {
      get { return _type; }
      set { _type = value; }
    }

    public InitiativeState InitiativeStatus
    {
      get { return _initiativeState; }
      set
      {
        InitiativeState oldState = _initiativeState;
        _initiativeState = value;
        if (_initiativeState != oldState && InitiativeStateChanged != null)
        {
          InitiativeStateChanged(this, oldState);
        }
      }
    }

    #endregion

    #region Public Subs/Functions

    public virtual void RollInitiative()
    {
      if (InitiativeStatus == InitiativeState.OutOfCombat)
      {
        if (RollForInitiative != null)
        {
          RollForInitiative.Invoke(this);
          InitiativeStatus = InitiativeState.InInitiative;
        }
      }
    }

    public virtual void StartTurn()
    {
      if (StartOfTurn != null)
      {
        StartOfTurn.Invoke(this);
      }
    }

    public virtual void EndTurn()
    {
      if (EndOfTurn != null)
      {
        EndOfTurn.Invoke(this);
      }
    }

    #endregion

    public event CreatureEvent RollForInitiative;
    public event CreatureEvent StartOfTurn;
    public event CreatureEvent EndOfTurn;
    public event InitiativeStateEvent InitiativeStateChanged;

    #region IComparable<Creature>

    public int CompareTo(Creature other)
    {
      if (InitiativeRoll > other.InitiativeRoll)
      {
        return -1;
      }
      else if (InitiativeRoll < other.InitiativeRoll)
      {
        return +1;
      }
      else if (InitiativeBonus > other.InitiativeBonus)
      {
        return -1;
      }
      else if (InitiativeBonus < other.InitiativeBonus)
      {
        return +1;
      }
      else if (Type == CreatureType.Player && other.Type == CreatureType.Monster)
      {
        return -1;
      }
      else if (Type == CreatureType.Monster && other.Type == CreatureType.Player)
      {
        return +1;
      }
      else
      {
        return Name.CompareTo(other.Name);
      }
    }

    #endregion

    #region IEquatable<Creature>
    public bool Equals(Creature other)
    {
      return Name == other.Name;
    }
    #endregion
  }

  public delegate void CreatureEvent(Creature sender);
  public delegate void InitiativeStateEvent(Creature sender, InitiativeState previousState);

  public enum CreatureType
  {
    Player,
    Monster
  }

  public enum InitiativeState
  {
    OutOfCombat,
    InInitiative,
    ReadiedAction,
    DelayedAction
  }
}